﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Media;

namespace CachingProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string path;        // The user-inputted path for a file
            string fullPath;    // The full path of the file calculated by the computer
            int cSize;          // Cache Size
            int bSize;          // Words per Block
            int assoc;          // the Associativity
            string sizeTemp, blockTemp, assocTemp;  // the actual string inputs from the user that will be converted to integers and stored
            string choice = "y";    // place to store the user's looping choice, needs to be 'y' at start

            // Initial Console Header
            Console.WriteLine("Taylor Lopez & Catherine Lyons\tCS4200\tSP11");
            Console.WriteLine("Caching Simulator");
            
            //All user interaction
            while (string.Equals("y", choice, StringComparison.OrdinalIgnoreCase))
            {
                // Prompt user for all needed fields
                // file path
                Console.WriteLine("Please enter the file name to check (in the same directory as EXE)");
                
                do{ // checks for the file's existence before proceeding
                    path = Console.ReadLine();
                    fullPath = System.IO.Path.GetFullPath(path);
                    if (File.Exists(fullPath) == false)
                        Console.WriteLine("That file does not exist, try again.");
                }while(File.Exists(fullPath) == false);

                // cache size
                Console.WriteLine("Please enter the size of the cache (in bytes)");
                sizeTemp = Console.ReadLine();
                cSize = Convert.ToInt32(sizeTemp);
                while (cSize > 65536)
                {
                    Console.WriteLine("The cache size you have entered exceeds 64K, please reenter a smaller value:");
                    sizeTemp = Console.ReadLine();
                    cSize = Convert.ToInt32(sizeTemp);
                }

                // block size
                Console.WriteLine("Please enter the size of the blocks (in bytes)");
                blockTemp = Console.ReadLine();
                bSize = Convert.ToInt32(blockTemp);
                while (bSize > 256)
                {
                    Console.WriteLine("The block size you have entered exceeds 256 bytes, please reenter a smaller value:");
                    blockTemp = Console.ReadLine();
                    bSize = Convert.ToInt32(blockTemp);
                }

                // associativity
                Console.WriteLine("Please enter the associativity");
                assocTemp = Console.ReadLine();
                assoc = Convert.ToInt32(assocTemp);
                bool test = (assoc != 0) && ((assoc & (assoc - 1)) == 0);
                while (test == false)
                {
                    // makes sure the given associativity is a power of 2 before proceeding
                    Console.WriteLine("The Associativity you have entered is not a power of 2. Try again.");
                    assocTemp = Console.ReadLine();
                    assoc = Convert.ToInt32(assocTemp);
                    test = (assoc != 0) && ((assoc & (assoc - 1)) == 0);
                }

                // All Cache interaction
                Meta meta = new Meta(fullPath, cSize, bSize, assoc);
                meta.DoMeta();

                // Print all results in readable format
                Console.WriteLine();
                Console.WriteLine("program_name:    " + path);
                Console.WriteLine("cache_size:      " + cSize);
                Console.WriteLine("block_size:      " + bSize);
                Console.WriteLine("associativity:   " + assoc);
                Console.WriteLine("total_lds:       " + (meta.Hit() + meta.Miss()).ToString());
                Console.WriteLine("cache_hits:      " + meta.Hit().ToString());
                Console.WriteLine("cache_misses:    " + meta.Miss().ToString());
                Console.WriteLine("cache_miss_rate: " + meta.MissRate().ToString());
                SystemSounds.Asterisk.Play();
                Console.WriteLine("\nDo you want to try another cache? Enter 'y' if yes, anything else to quit");
                Console.ReadLine();
            }
            
        }
    }
}